package graphing;

import graphics.Graphable2D;
import graphicsExtended.ResettableGraphics;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Stroke;
import math.vectorSpace.R2.Point2D;

/**
 *
 * Fully Tested: No
 * Fully Documented: No
 * Created: 21-Apr-2012
 * Last Updated: 21-Apr-2012
 *
 * @author Shimu Wu
 */
public class GraphGrid {

    private final BasicStroke GRID, AXIS, ASYMPTOTE;

    /** The color of the grid, axis, and asymptote */
    private final Color gridColor, axisColor, asymptoteColor;

    /** The width of the screen */
    private final int screenWidth;

    /** The height of the screen */
    private final int screenHeight;

    private double xMin, xMax, xScale, yMin, yMax, yScale;

    private double xMagnification, yMagnification;

    public GraphGrid(Color gridColor, int gridWidth,
            Color axisColor, int axisWidth, Color asymptoteColor,
            int asymptoteWidth, int screenWidth, int screenHeight,
            double xMin, double xMax, double yMin, double yMax) {

        this.gridColor = gridColor;
        this.axisColor = axisColor;
        this.asymptoteColor = asymptoteColor;

        GRID = new BasicStroke(gridWidth);
        AXIS = new BasicStroke(axisWidth);

        float dashArray[] = {10.0f};
        ASYMPTOTE = new BasicStroke(asymptoteWidth, BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER, 10.0f, dashArray, 0.0f);


        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;

        this.xMin = xMin;
        this.xMax = xMax;
        this.yMin = yMin;
        this.yMax = yMax;

        this.xScale = (xMax - xMin) / 20.0;
        this.yScale = (yMax - yMin) / 20.0;

        this.xMagnification = screenWidth / (xMax - xMin);
        this.yMagnification = screenHeight / (yMax - yMin);

    }

    public GraphGrid(int screenWidth, int screenHeight,
            double xMin, double xMax, double yMin, double yMax) {
        this(Color.GRAY, 1, Color.BLACK, 6, Color.BLUE, 3,
                screenWidth, screenHeight, xMin, xMax, yMin, yMax);
    }

    public void drawGrid(Graphics2D graphics) {
        // Used to set the color back to what it original was
        ResettableGraphics graphicSetter = new ResettableGraphics(graphics);

        graphicSetter.set(gridColor, GRID);

        // This draws vertical grid lines
        int maxValue = (int) (screenWidth / (xScale * xMagnification));
        for (int i = 0; i < maxValue; i++) {
            graphics.drawLine(
                    (int) ((i * xScale + (xMin % xScale)) * xMagnification), 0,
                    (int) ((i * xScale + (xMin % xScale)) * xMagnification),
                    screenHeight);
        }

        // This draws horizontal grid lines
        maxValue = (int) (screenHeight / (yScale * yMagnification));
        for (int i = 0; i < maxValue; i++) {
            graphics.drawLine(0,
                    (int) ((i * yScale + (yMin % yScale)) * yMagnification),
                    screenWidth,
                    (int) ((i * yScale + (yMin % yScale)) * yMagnification));
        }

        graphicSetter.set(axisColor, AXIS);

        // This draws the x-axis
        if (yMin <= 0) {
            int yCoord = screenHeight
                    - (int) (-yMin * yMagnification);
            graphics.drawLine(0, yCoord, screenWidth, yCoord);
        }

        // This draws the y-axis
        if (xMin <= 0) {
            int xCoord = (int) (-xMin * xMagnification);
            graphics.drawLine(xCoord, 0, xCoord, screenHeight);
        }

        graphicSetter.reset();
    }

    private void drawLine(Graphics2D graphics, Point2D p1, Point2D p2) {
        
    }

    public void drawEquation(Graphics2D graphics, Graphable2D equation,
            Color equationColor, int equationWidth) {

        double x, y;
        x = xMin;
        y = equation.evaluate(x);

        ResettableGraphics graphicSetter = new ResettableGraphics(graphics);
        graphicSetter.set(equationColor, new BasicStroke(equationWidth));

        Point2D shift, magnification, p1, p2;
        shift = new Point2D(Math.abs(xMin), Math.abs(yMin));
        magnification = new Point2D(xMagnification, yMagnification);

        p1 = new Point2D(Integer.MIN_VALUE, Integer.MIN_VALUE);

        p2 = new Point2D(x, y);
        p2.add(shift);
        p2.multiply(magnification);

        while (p1.getX() < screenWidth) {
            p1 = p2.copy();

            x += 1 / xMagnification;
            y = equation.evaluate(x);

            p2 = new Point2D(x, y);
            p2.add(shift);
            p2.multiply(magnification);

            drawLine(graphics, p1, p2);
        }

        graphicSetter.reset();
        /*
        } else {
        DrawAsymptote
        }
        GraphicalY2 = (int) ((thisEquation.evaluateAt(x) + yMin) * yMagnification);
        GraphicalX2 = (int) ((x + xMin) * xMagnification);
         */
    }
}
